package com.vertxsample.samples.core.web

import com.vertxsample.samples.core.web.annotation.ClassUtils
import com.vertxsample.samples.core.web.annotation.HttpAPI
import com.vertxsample.samples.core.web.annotation.HttpController
import io.vertx.core.AbstractVerticle
import io.vertx.core.Handler
import io.vertx.core.Vertx
import io.vertx.core.http.HttpServerResponse
import io.vertx.ext.web.Router
import io.vertx.ext.web.RoutingContext
import org.apache.logging.log4j.LogManager
import org.jooq.DSLContext
import java.lang.reflect.Method
import java.util.concurrent.CompletableFuture

//基础服务类
open class BaseNodeVerticle : AbstractVerticle() {
    private val logger = LogManager.getLogger(BaseNodeVerticle::class.java!!.getName())
    //根据注解设置路由
    public open fun configRouterByAnnotation(packageName:String,router: Router, dslContext: DSLContext){
        ClassUtils.scanPackageByAnnotation(packageName,false, HttpController::class.java ).stream()
            .forEach { c->


                val routerUri1=c.getAnnotation(HttpController::class.java).routerUri;
                ClassUtils.scanFunctionByAnnotation(c, HttpAPI::class.java).stream()
                    .forEach {
                            m->

                        val api=m.getDeclaredAnnotation(HttpAPI::class.java);
                        logger.info("mapping url:"+ routerUri1+ api.routerUri +" to "+c.name+"."+m.name)
                        if(api.method!=null) {
                            router.route(api.method, routerUri1 + api.routerUri)
                                .handler(HttpHandler(c, m, api, vertx, dslContext));
                        } else {
                            router.route(routerUri1 + api.routerUri)
                                .handler(HttpHandler(c, m, api, vertx, dslContext));
                        }

                    }
            }
    }



    class HttpHandler(val controllerClass : Class<*>, val method : Method, val api: HttpAPI, val vertx : Vertx, val dslContext: DSLContext):
        Handler<RoutingContext> {
        override fun handle(routingContext: RoutingContext?) {
            val controller=controllerClass.getConstructor(RequestContext::class.java).newInstance(RequestContext(vertx,
                routingContext!!,dslContext))

            val  future=method.invoke(controller) as CompletableFuture<String>
            if(api.returnType=="json") {
                future.thenAccept { it ->
                    routingContext.response().json().end(it)
                }
            }else
                if(api.returnType=="html") {
                    future.thenAccept { it ->
                        routingContext.response().html().end(it)
                    }
                }

        }
        fun HttpServerResponse.json() : HttpServerResponse {
            return this.putHeader("content-type","application/json; charset=utf-8")
        }
        fun HttpServerResponse.html() : HttpServerResponse {
            return this.putHeader("content-type","text/html")
        }

    }
}